#include "GY_GraphicsFillet.h"
GY_GraphicsFillet::GY_GraphicsFillet(const QString &guid, QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("Fillet"));
    initializationPropertyInfo();
    QMap<QVariant,QPointF> editPoints = {
        {"Point1",m_PropertyInfoMap["Point1"].propertyValue.toPointF()},
        {"Point2",m_PropertyInfoMap["Point2"].propertyValue.toPointF()}
    };
    updateDraw();
    this->setPen(QColor(0,255,0));
    this->setEditPointF(editPoints);
}

GY_GraphicsFillet::GY_GraphicsFillet(const QString &guid,
                                     const QPointF &point1, const QPointF &point2,
                                     qreal radius1, qreal radius2, qreal radius3, qreal radius4,
                                     QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("Fillet"));
    initializationPropertyInfo();
    m_PropertyInfoMap["Point1"].propertyValue=point1;
    m_PropertyInfoMap["Point2"].propertyValue=point2;
    m_PropertyInfoMap["Radius1"].propertyValue=radius1;
    m_PropertyInfoMap["Radius2"].propertyValue=radius2;
    m_PropertyInfoMap["Radius3"].propertyValue=radius3;
    m_PropertyInfoMap["Radius4"].propertyValue=radius4;
    QMap<QVariant,QPointF> editPoints = {
        {"Point1",m_PropertyInfoMap["Point1"].propertyValue.toPointF()},
        {"Point2",m_PropertyInfoMap["Point2"].propertyValue.toPointF()}
    };
    updateDraw();
    this->setPen(QColor(0,255,0));
    this->setEditPointF(editPoints);
}

bool GY_GraphicsFillet::updatePoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF mousePoint = this->mapFromScene(value.value<QPointF>());
    m_PropertyInfoMap[name].propertyValue=mousePoint;
    updateDraw();
    this->setEditPointF(name,mousePoint);
    return true;
}

bool GY_GraphicsFillet::updateRadius(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}
/**
 * @brief updateDarw  更新绘制图形
 */
void GY_GraphicsFillet::updateDraw()
{
    //获取存储属性信息
    QPointF point1=m_PropertyInfoMap.value("Point1").propertyValue.toPointF();
    QPointF point2=m_PropertyInfoMap.value("Point2").propertyValue.toPointF();
    qreal radius1 = m_PropertyInfoMap.value("Radius1").propertyValue.value<qreal>();
    qreal radius2 = m_PropertyInfoMap.value("Radius2").propertyValue.value<qreal>();
    qreal radius3 = m_PropertyInfoMap.value("Radius3").propertyValue.value<qreal>();
    qreal radius4 = m_PropertyInfoMap.value("Radius4").propertyValue.value<qreal>();
    //定义绘制参数
    QPointF startPoint=point1;
    QPointF endPoint=point2;
    qreal leftBottomRadius=radius1;
    qreal leftTopRadius=radius2;
    qreal rightTopRadius=radius3;
    qreal rightBottomRadius=radius4;
    //根据Point1和Point2的相对位置对绘制参数进行排序矫正
    if(point1.x()>point2.x()&&point1.y()<point2.y())
    {
        startPoint=QPointF(point2.x(),point1.y());
        endPoint=QPointF(point1.x(),point2.y());
        leftBottomRadius=radius4;
        leftTopRadius=radius3;
        rightTopRadius=radius2;
        rightBottomRadius=radius1;
    }
    else if(point1.x()>point2.x()&&point1.y()>point2.y())
    {
        startPoint=point2;
        endPoint=point1;
        leftBottomRadius=radius3;
        leftTopRadius=radius4;
        rightTopRadius=radius1;
        rightBottomRadius=radius2;
    }
    else if(point1.x()<point2.x()&&point1.y()>point2.y())
    {
        startPoint=QPointF(point1.x(),point2.y());
        endPoint=QPointF(point2.x(),point1.y());
        leftBottomRadius=radius2;
        leftTopRadius=radius1;
        rightTopRadius=radius4;
        rightBottomRadius=radius3;
    }
    //矫正半径(当宽高的一半小于半径时需要矫正半径)
    qreal height=qAbs(endPoint.y()-startPoint.y());
    qreal width=qAbs(endPoint.x()-startPoint.x());
    leftBottomRadius=leftBottomRadius>qMin(width,height)/2?qMin(width,height)/2:leftBottomRadius;
    leftTopRadius=leftTopRadius>qMin(width,height)/2?qMin(width,height)/2:leftTopRadius;
    rightTopRadius=rightTopRadius>qMin(width,height)/2?qMin(width,height)/2:rightTopRadius;
    rightBottomRadius=rightBottomRadius>qMin(width,height)/2?qMin(width,height)/2:rightBottomRadius;
    //更新绘制的Path
    updatePath(startPoint,endPoint,leftBottomRadius,leftTopRadius,rightTopRadius,rightBottomRadius);

}
/**
 * @brief updatePath 更新图形path
 * @param startPoint 开始点(默认左下角点)
 * @param endPof leftTopRadius 左上角圆弧半径
 * @param rightTopRadius 右上角圆弧半径
 * @param rightBottomRadius 右下角圆弧半径
 */
void GY_GraphicsFillet::updatePath(const QPointF &startPoint, const QPointF &endPoint, const qreal leftBottomRadius, const qreal leftTopRadius, const qreal rightTopRadius, const qreal rightBottomRadius)
{
    QPainterPath path;//width=100,height=50,positionPoint(0,0),sizePoint(100,50),cornerRadius=10
    path.moveTo(startPoint.x()+leftBottomRadius,startPoint.y());//p1(10,0)
    //左下圆弧//p2(0,0)
    path.arcTo(startPoint.x(),startPoint.y(),leftBottomRadius*2,leftBottomRadius*2,90.0f,90.0f);
    //左边//p3(0,40)
    path.lineTo(startPoint.x(),endPoint.y()-leftTopRadius);
    //左上圆弧
    path.arcTo(startPoint.x(),endPoint.y()-leftTopRadius*2,leftTopRadius*2,leftTopRadius*2,180.0f,90.0f);
    //上边
    path.lineTo(endPoint.x()-rightTopRadius,endPoint.y());
    //右上圆弧
    path.arcTo(endPoint.x()-rightTopRadius*2,endPoint.y()-rightTopRadius*2,rightTopRadius*2,rightTopRadius*2,270.0f,90.0f);
    //右边
    path.lineTo(endPoint.x(),startPoint.y()+rightBottomRadius);
    //右下圆弧
    path.arcTo(endPoint.x()-rightBottomRadius*2,startPoint.y(),rightBottomRadius*2,rightBottomRadius*2,0.0f,90.0f);
    path.closeSubpath();
    this->setPath(path);
}

void GY_GraphicsFillet::initializationPropertyInfo()
{   
    QPointF Position = QPointF(0,0);//开始的坐标或中心点坐标
    QPointF point1 = QPointF(1,1);//结束的坐标或径向梯度的焦点坐标
    QPointF point2 = QPointF(-1,-1);//结束的坐标或径向梯度的焦点坐标
    QVector<qreal> varGradientStyle;
    varGradientStyle<<Position.x()<<Position.y()<<point1.x()<<point1.y()<<point2.x()<<point2.y();


    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap["ObjectName"].setConnect();

    GY_PropertyInfo IsVisible(this);
    IsVisible.propertyName = "IsVisible";
    IsVisible.propertyValue = true;
    IsVisible.updateType = Update|OrdinaryAttributes;
    IsVisible.propertyType = BoolPropertyType;
    IsVisible.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateIsVisible;
    m_PropertyInfoMap.insert("IsVisible",IsVisible);
    m_PropertyInfoMap["IsVisible"].setConnect();

    GY_PropertyInfo IsOutLined(this);
    IsOutLined.propertyName = "IsOutlined";
    IsOutLined.propertyValue = true;
    IsOutLined.updateType = Update|OrdinaryAttributes;
    IsOutLined.propertyType = BoolPropertyType;
    IsOutLined.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateIsOutLined;
    m_PropertyInfoMap.insert("IsOutlined",IsOutLined);
    m_PropertyInfoMap["IsOutlined"].setConnect();

    GY_PropertyInfo IsFilled(this);
    IsFilled.propertyName = "IsFilled";
    IsFilled.propertyValue = true;
    IsFilled.updateType = Update|OrdinaryAttributes;
    IsFilled.propertyType = BoolPropertyType;
    IsFilled.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateIsFilled;
    m_PropertyInfoMap.insert("IsFilled",IsFilled);
    m_PropertyInfoMap["IsFilled"].setConnect();

    GY_PropertyInfo IsAntialiased(this);
    IsAntialiased.propertyName = "IsAntialiased";
    IsAntialiased.propertyValue = true;
    IsAntialiased.updateType = Update|OrdinaryAttributes;
    IsAntialiased.propertyType = BoolPropertyType;
    IsAntialiased.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateIsAntialiased;
    m_PropertyInfoMap.insert("IsAntialiased",IsAntialiased);
    m_PropertyInfoMap["IsAntialiased"].setConnect();

    GY_PropertyInfo FillAttributes(this);
    FillAttributes.propertyName = "FillAttributes";
    FillAttributes.propertyValue = false;
    FillAttributes.updateType = Update|OrdinaryAttributes;
    FillAttributes.propertyType = BoolPropertyType;
    FillAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateFillAttributes;
    m_PropertyInfoMap.insert("FillAttributes",FillAttributes);
    m_PropertyInfoMap["FillAttributes"].setConnect();

    GY_PropertyInfo FillGradient(this);
    FillGradient.propertyName = "FillGradient";
    FillGradient.propertyValue = QVariant();
    FillGradient.updateType = Update|OrdinaryAttributes;
    FillGradient.propertyType = FillGradientPropertyType;
    FillGradient.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateFillGradient;
    m_PropertyInfoMap.insert("FillGradient",FillGradient);
    m_PropertyInfoMap["FillGradient"].setConnect();

    GY_PropertyInfo FillColor(this);
    FillColor.propertyName = "FillColor";
    FillColor.propertyValue = QColor();
    FillColor.updateType = Update|OrdinaryAttributes;
    FillColor.propertyType = ColorPropertyType;
    FillColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateFillColor;
    m_PropertyInfoMap.insert("FillColor",FillColor);
    m_PropertyInfoMap["FillColor"].setConnect();

    GY_PropertyInfo FillStyle(this);
    FillStyle.propertyName = "FillStyle";
    FillStyle.propertyValue = true;
    FillStyle.updateType = Update|OrdinaryAttributes;
    FillStyle.propertyType = FillStylePropertyType;
    FillStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateFillStyle;
    m_PropertyInfoMap.insert("FillStyle",FillStyle);
    m_PropertyInfoMap["FillStyle"].setConnect();

    GY_PropertyInfo FillOpacity(this);
    FillOpacity.propertyName = "FillOpacity";
    FillOpacity.propertyValue = qreal(1);
    FillOpacity.updateType = Update|OrdinaryAttributes;
    FillOpacity.propertyType = IntPropertyType;
    FillOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateFillOpacity;
    m_PropertyInfoMap.insert("FillOpacity",FillOpacity);
    m_PropertyInfoMap["FillOpacity"].setConnect();

    GY_PropertyInfo Pattern(this);
    Pattern.propertyName = "Pattern";
    Pattern.propertyValue = QVariant();
    Pattern.updateType = Update|OrdinaryAttributes;
    Pattern.propertyType = PatternPropertyType;
    Pattern.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePattern;
    m_PropertyInfoMap.insert("Pattern",Pattern);
    m_PropertyInfoMap["Pattern"].setConnect();

    GY_PropertyInfo PenColor(this);
    PenColor.propertyName = "PenColor";
    PenColor.propertyValue = QColor(255,255,255);
    PenColor.updateType = Update|OrdinaryAttributes;
    PenColor.propertyType = ColorPropertyType;
    PenColor.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePenColor;
    m_PropertyInfoMap.insert("PenColor",PenColor);
    m_PropertyInfoMap["PenColor"].setConnect();

    GY_PropertyInfo PenAttributes(this);
    PenAttributes.propertyName = "PenAttributes";
    PenAttributes.propertyValue = false;
    PenAttributes.updateType = Update|OrdinaryAttributes;
    PenAttributes.propertyType = BoolPropertyType;
    PenAttributes.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePenAttributes;
    m_PropertyInfoMap.insert("PenAttributes",PenAttributes);
    m_PropertyInfoMap["PenAttributes"].setConnect();

    GY_PropertyInfo PenOpacity(this);
    PenOpacity.propertyName = "PenOpacity";
    PenOpacity.propertyValue = qreal(1);
    PenOpacity.updateType = Update|OrdinaryAttributes;
    PenOpacity.propertyType = IntPropertyType;
    PenOpacity.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePenOpacity;
    m_PropertyInfoMap.insert("PenOpacity",PenOpacity);
    m_PropertyInfoMap["PenOpacity"].setConnect();

    GY_PropertyInfo LineStyle(this);
    LineStyle.propertyName = "LineStyle";
    QVector<qreal> lineStyle;
    int style = Qt::SquareCap|Qt::BevelJoin|Qt::CustomDashLine;
    lineStyle<<style<<2<<3<<4<<5<<6<<7;//自定义矩形线框样式
    LineStyle.propertyValue = QVariant();
    LineStyle.updateType = Update|OrdinaryAttributes;
    LineStyle.propertyType = LineStylePropertyType;
    LineStyle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateLineStyle;
    m_PropertyInfoMap.insert("LineStyle",LineStyle);
    m_PropertyInfoMap["LineStyle"].setConnect();

    GY_PropertyInfo point1Property(this);
    point1Property.propertyName="Point1";
    point1Property.propertyValue=QPointF(0,0);
    point1Property.updateType = MoveUpdate|Update|PointOfRelative;
    point1Property.propertyType = PointPropertyType;
    point1Property.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePoint;
    m_PropertyInfoMap.insert(point1Property.propertyName,point1Property);
    m_PropertyInfoMap["Point1"].setConnect();

    GY_PropertyInfo point2Property(this);
    point2Property.propertyName="Point2";
    point2Property.propertyValue=QPointF(200,100);
    point2Property.updateType = MoveUpdate|Update|PointOfRelative;
    point2Property.propertyType = PointPropertyType;
    point2Property.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updatePoint;
    m_PropertyInfoMap.insert("Point2",point2Property);
    m_PropertyInfoMap["Point2"].setConnect();

    GY_PropertyInfo Radius1(this);
    Radius1.propertyName = "Radius1";
    Radius1.propertyValue = qreal(10);
    Radius1.updateType = Update|OrdinaryAttributes;
    Radius1.propertyType = QrealPropertyType;
    Radius1.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateRadius;
    m_PropertyInfoMap.insert("Radius1",Radius1);
    m_PropertyInfoMap["Radius1"].setConnect();

    GY_PropertyInfo Radius2(this);
    Radius2.propertyName = "Radius2";
    Radius2.propertyValue = qreal(10);
    Radius2.updateType = Update|OrdinaryAttributes;
    Radius2.propertyType = QrealPropertyType;
    Radius2.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateRadius;
    m_PropertyInfoMap.insert("Radius2",Radius2);
    m_PropertyInfoMap["Radius2"].setConnect();

    GY_PropertyInfo Radius3(this);
    Radius3.propertyName = "Radius3";
    Radius3.propertyValue = qreal(10);
    Radius3.updateType = Update|OrdinaryAttributes;
    Radius3.propertyType = QrealPropertyType;
    Radius3.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateRadius;
    m_PropertyInfoMap.insert("Radius3",Radius3);
    m_PropertyInfoMap["Radius3"].setConnect();

    GY_PropertyInfo Radius4(this);
    Radius4.propertyName = "Radius4";
    Radius4.propertyValue = qreal(10);
    Radius4.updateType = Update|OrdinaryAttributes;
    Radius4.propertyType = QrealPropertyType;
    Radius4.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsFillet::updateRadius;
    m_PropertyInfoMap.insert("Radius4",Radius4);
    m_PropertyInfoMap["Radius4"].setConnect();
}
